#include "WavPlayer.h"

void delay_ms (WORD);	/* Defined in asmfunc.S */
void delay_us (WORD);	/* Defined in asmfunc.S */

volatile BYTE FifoRi, FifoWi, FifoCt;	/* FIFO controls */
BYTE Buff[256];		/* Wave output FIFO */
WORD byteRead;            //Bytes read

static
DWORD load_header (FATFS *fs)	/* 0:Invalid format, 1:I/O error, >1:Number of samples */
{
	DWORD size, freq;
	BYTE b, al = 0;

	if (pf_read(Buff, 12, &byteRead)) return 1;	/* Load file header (12 bytes) */

	if (byteRead != 12 || LD_DWORD(Buff+8) != FCC('W','A','V','E')) return 0;

	for (;;) {
		//wdt_reset();
		pf_read(Buff, 8, &byteRead);			/* Get Chunk ID and size */
		if (byteRead != 8) return 0;
		size = LD_DWORD(&Buff[4]);		/* Chunk size */

		switch (LD_DWORD(&Buff[0])) {	/* FCC */
		case FCC('f','m','t',' ') :					/* 'fmt ' chunk */
			if (size & 1) size++;
			if (size > 100 || size < 16) return 0;		/* Check chunk size */
			pf_read(Buff, size, &byteRead);					/* Get content */
			if (byteRead != size) return 0;
			if (Buff[0] != 1) return 0;				/* Check coding type (1) */
			b = Buff[2];
			if (b != 1 && b != 2) return 0;			/* Check channels (1/2) */
			GPIOR0 = al = b;						/* Save channel flag */
			b = Buff[14];
			if (b != 8 && b != 16) return 0;		/* Check resolution (8/16 bit) */
			GPIOR0 |= b;							/* Save resolution flag */
			if (b & 16) al <<= 1;
			freq = LD_DWORD(&Buff[4]);					/* Check sampling freqency (8k-48k) */
			if (freq < 8000 || freq > 48000) return 4;
			PLAYBACK_RATE = 1000;//(WORD)((DWORD)(F_CPU) / 44100) - 1;		/* Sampling freq */
			break;

		case FCC('d','a','t','a') :		/* 'data' chunk (start to play) */
			if (!al) return 0;							/* Check if format valid */
			if (size < 1024 || (size & (al - 1))) return 0;	/* Check size */
			if (fs->fptr & (al - 1)) return 0;			/* Check offset */
			return size;

		case FCC('D','I','S','P') :		/* 'DISP' chunk (skip) */
		case FCC('L','I','S','T') :		/* 'LIST' chunk (skip) */
		case FCC('f','a','c','t') :		/* 'fact' chunk (skip) */
			if (size & 1) size++;
			pf_lseek(fs->fptr + size);
			break;

		default :						/* Unknown chunk (error) */
			return 0;
		}
	}

	return 0;
}

void ramp (
	int dir		/* 0:Ramp-down, 1:Ramp-up */
)
{
	BYTE v, d, n;


	if (dir) {
		v = 0; d = 1;
	} else {
		v = 128; d = (BYTE)-1;
	}

	n = 128;
	do {
		v += d;
		SPK_OUT = v;
		delay_us(100);
	} while (--n);
}

FRESULT play (
	const char *dir,	/* Directory */
	const char *fn,		/* File */
    FATFS *fs
)
{
	DWORD sz;
	FRESULT res;
	WORD btr;

	strcpy((char*)Buff, dir);	/* sprintf(Buff, "%s/%s", dir, fn); */
	strcat((char*)Buff, "/");
	strcat((char*)Buff, fn);

	res = pf_open((char*)Buff);		/* Open sound file */
	if (res == FR_OK) {
		sz = load_header(fs);			/* Load file header */
		if (sz < 256) return 255;

		FifoCt = 0; FifoRi = 0; FifoWi = 0;		/* Reset FIFO */
		pf_read(0, 512 - (fs->fptr % 512), &byteRead);	/* Snip sector unaligned part */
		sz -= byteRead;

		do {
			/* Forward audio data */
			btr = (sz > 1024) ? 1024 : (WORD)sz;
			res = pf_read(0, btr, &byteRead);
			if (res != FR_OK || btr != byteRead) break;
			sz -= byteRead;
			if (bit_is_clear(MOSI_PIN,MOSI_PINNUM)) break;
		} while (byteRead == 1024);	/* Repeat until all data read */
	}

	while (FifoCt) ;			/* Wait for FIFO empty */
	SPK_OUT = 128;

	return res;
}
